package org.dizena.base.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.dizena.base.enums.Constant;
import org.dizena.base.enums.State;
import org.dizena.modules.master.bean.User;
import org.dizena.modules.master.service.UserService;
import org.dizena.utils.ObjectUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

@Slf4j
@Component
public class SessionUserRealm extends AuthorizingRealm
{

    @Resource
    private UserService service;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
    {
        try
        {
            String key = (String) getAvailablePrincipal(principals);
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            Object tmp = session.getAttribute(session.getId().toString());
            User user = null;
            if (null != tmp)
            {
                user = (User) tmp;
            }
            else
            {
                user = service.queryByAccount(key);
            }

            Set<String> roleNames = new HashSet<String>(ObjectUtil.str2List(user.getRoles(), ","));
            Set<String> permissions = new TreeSet<String>(ObjectUtil.str2List(user.getAuths(), ","));

            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.setRoles(roleNames);
            info.setStringPermissions(permissions);
            return info;
        }
        catch (Exception e)
        {
            return null;
        }
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
    {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        if (upToken != null && upToken.getUsername() != null)
        {
            String account = upToken.getUsername();
            char[] cs = upToken.getPassword();
            String passwd = null;
            if (cs != null)
            {
                passwd = new String(upToken.getPassword());
            }
            User user = service.queryByAccount(account);
            if (user == null)
            {
                throw new RuntimeException("账户不存在");
            }
            if (State.LOCK.getState().equals(user.getLocked()))
            {
                throw new RuntimeException("账户锁定");
            }
            String pwd = DigestUtils.md5Hex(user.getSalt() + passwd);
            if (user.getPasswd().equals(pwd))
            {
                SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(account, passwd, getName());
                // 加入session
                Session session = SecurityUtils.getSubject().getSession();
                session.setAttribute(Constant.CurrentUser, user);
                return info;
            }
        }
        return null;
    }
}
